﻿namespace DomainServices.Tools
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Text;

    internal class LinkedServerProjectCache
    {
        private string _historyFilePath;
        private bool _isFileCacheCurrent;
        private Dictionary<string, string> _linkedServerProjectsByProject;
        private ILogger _logger;
        private ProjectFileReader _projectFileReader;
        private string _rootProjectPath;
        private const string LinkedServerProjectPropertyName = "LinkedServerProject";

        internal LinkedServerProjectCache(string rootProjectPath, string historyFilePath, ILogger logger, ProjectFileReader projectFileReader)
        {
            if (string.IsNullOrEmpty(rootProjectPath))
            {
                throw new ArgumentNullException("rootProjectPath");
            }
            if (string.IsNullOrEmpty(historyFilePath))
            {
                throw new ArgumentNullException("historyFilePath");
            }
            if (logger == null)
            {
                throw new ArgumentNullException("logger");
            }
            if (projectFileReader == null)
            {
                throw new ArgumentNullException("projectFileReader");
            }
            this._rootProjectPath = rootProjectPath;
            this._historyFilePath = historyFilePath;
            this._logger = logger;
            this._projectFileReader = projectFileReader;
        }

        internal IEnumerable<string> GetLinkedServerProjectSources(string linkedServerProject)
        {
            return (from s in this.ProjectReferences
                where string.Equals(linkedServerProject, this[s], StringComparison.OrdinalIgnoreCase)
                select s);
        }

        internal bool LoadCacheFromFile()
        {
            this.IsFileCacheCurrent = false;
            if (!File.Exists(this._historyFilePath))
            {
                return false;
            }
            DateTime lastWriteTime = File.GetLastWriteTime(this._rootProjectPath);
            DateTime time2 = File.GetLastWriteTime(this._historyFilePath);
            if (lastWriteTime.CompareTo(time2) > 0)
            {
                return false;
            }
            foreach (string str2 in File.ReadAllText(this._historyFilePath).Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries))
            {
                string str3 = null;
                string[] strArray2 = str2.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                if (strArray2.Length < 2)
                {
                    this.LinkedServerProjectsByProject.Clear();
                    return false;
                }
                string path = strArray2[0];
                if (File.Exists(path))
                {
                    if (File.GetLastWriteTime(path).CompareTo(time2) > 0)
                    {
                        str3 = this.LoadRiaLinkFromProject(path);
                    }
                    else if (strArray2.Length == 3)
                    {
                        str3 = strArray2[2];
                    }
                    this[path] = str3;
                }
            }
            this.IsFileCacheCurrent = true;
            return true;
        }

        internal void LoadCacheFromProject()
        {
            this._linkedServerProjectsByProject.Clear();
            this.IsFileCacheCurrent = false;
            foreach (string str in this._projectFileReader.LoadProjectReferences(this._rootProjectPath))
            {
                string str2 = this.LoadRiaLinkFromProject(str);
                this[str] = str2;
            }
        }

        internal string LoadRiaLinkFromProject(string projectPath)
        {
            string propertyValue = this._projectFileReader.GetPropertyValue(projectPath, "LinkedServerProject");
            if (!string.IsNullOrEmpty(propertyValue))
            {
                propertyValue = ProjectFileReader.ConvertToFullPath(propertyValue, projectPath);
                this._logger.LogMessage(string.Format(CultureInfo.CurrentCulture, Resource.RIA_Link_Present, new object[] { projectPath, propertyValue }));
            }
            return propertyValue;
        }

        internal bool SaveCacheToFile()
        {
            if (string.IsNullOrEmpty(this._historyFilePath) || (this._linkedServerProjectsByProject == null))
            {
                return false;
            }
            StringBuilder builder = new StringBuilder();
            foreach (string str in this.LinkedServerProjectsByProject.Keys)
            {
                StringBuilder builder2 = new StringBuilder();
                builder2.Append(str);
                builder2.Append(',');
                builder2.Append(File.GetLastWriteTime(str).Ticks.ToString(CultureInfo.InvariantCulture));
                builder2.Append(',');
                string str2 = this[str];
                if (!string.IsNullOrEmpty(str2))
                {
                    builder2.Append(str2);
                }
                builder.AppendLine(builder2.ToString());
            }
            Exception exception = null;
            try
            {
                File.WriteAllText(this._historyFilePath, builder.ToString());
            }
            catch (IOException exception2)
            {
                exception = exception2;
            }
            catch (UnauthorizedAccessException exception3)
            {
                exception = exception3;
            }
            if (exception != null)
            {
                this._logger.LogWarning(string.Format(CultureInfo.CurrentCulture, Resource.Failed_To_Write_File, new object[] { this._historyFilePath, exception.Message }));
                return false;
            }
            this.IsFileCacheCurrent = true;
            return true;
        }

        internal bool IsFileCacheCurrent
        {
            get
            {
                return this._isFileCacheCurrent;
            }
            private set
            {
                this._isFileCacheCurrent = value;
            }
        }

        internal string this[string projectPath]
        {
            get
            {
                if (string.IsNullOrEmpty(projectPath))
                {
                    throw new ArgumentNullException("projectPath");
                }
                string str = null;
                this.LinkedServerProjectsByProject.TryGetValue(projectPath, out str);
                return str;
            }
            set
            {
                if (string.IsNullOrEmpty(projectPath))
                {
                    throw new ArgumentNullException("projectPath");
                }
                this.LinkedServerProjectsByProject[projectPath] = value;
                this.IsFileCacheCurrent = false;
            }
        }

        internal IEnumerable<string> LinkedServerProjects
        {
            get
            {
                return (from s in this.LinkedServerProjectsByProject.Values
                    where !string.IsNullOrEmpty(s)
                    select s).Distinct<string>();
            }
        }

        internal Dictionary<string, string> LinkedServerProjectsByProject
        {
            get
            {
                if (this._linkedServerProjectsByProject == null)
                {
                    this._linkedServerProjectsByProject = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
                    if (!this.LoadCacheFromFile())
                    {
                        this.LoadCacheFromProject();
                    }
                }
                return this._linkedServerProjectsByProject;
            }
        }

        internal IEnumerable<string> ProjectReferences
        {
            get
            {
                return this.LinkedServerProjectsByProject.Keys;
            }
        }
    }
}

